package com.appspot.eusms.sms;

import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.SmsMessage;

import com.appspot.eusms.util.GroupUtil;

import org.whispersystems.textsecure.push.IncomingPushMessage;
import org.whispersystems.textsecure.storage.RecipientDevice;

import java.util.List;

import static org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent.GroupContext;

public class IncomingTextMessage implements Parcelable {

    public static final Creator<IncomingTextMessage> CREATOR = new Creator<IncomingTextMessage>() {
        @Override
        public IncomingTextMessage createFromParcel(Parcel in) {
            return new IncomingTextMessage(in);
        }

        @Override
        public IncomingTextMessage[] newArray(int size) {
            return new IncomingTextMessage[size];
        }
    };

    private final String message;
    private final String sender;
    private final int senderDeviceId;
    private final int protocol;
    private final String serviceCenterAddress;
    private final boolean replyPathPresent;
    private final String pseudoSubject;
    private final long sentTimestampMillis;
    private final String groupId;
    private final boolean push;

    public IncomingTextMessage(SmsMessage message) {
        this.message = message.getDisplayMessageBody();
        this.sender = message.getDisplayOriginatingAddress();
        this.senderDeviceId = RecipientDevice.DEFAULT_DEVICE_ID;
        this.protocol = message.getProtocolIdentifier();
        this.serviceCenterAddress = message.getServiceCenterAddress();
        this.replyPathPresent = message.isReplyPathPresent();
        this.pseudoSubject = message.getPseudoSubject();
        this.sentTimestampMillis = message.getTimestampMillis();
        this.groupId = null;
        this.push = false;
    }

    public IncomingTextMessage(IncomingPushMessage message, String encodedBody, GroupContext group) {
        this.message = encodedBody;
        this.sender = message.getSource();
        this.senderDeviceId = message.getSourceDevice();
        this.protocol = 31337;
        this.serviceCenterAddress = "GCM";
        this.replyPathPresent = true;
        this.pseudoSubject = "";
        this.sentTimestampMillis = message.getTimestampMillis();
        this.push = true;

        if (group != null && group.hasId()) {
            this.groupId = GroupUtil.getEncodedId(group.getId().toByteArray());
        } else {
            this.groupId = null;
        }
    }

    public IncomingTextMessage(Parcel in) {
        this.message = in.readString();
        this.sender = in.readString();
        this.senderDeviceId = in.readInt();
        this.protocol = in.readInt();
        this.serviceCenterAddress = in.readString();
        this.replyPathPresent = (in.readInt() == 1);
        this.pseudoSubject = in.readString();
        this.sentTimestampMillis = in.readLong();
        this.groupId = in.readString();
        this.push = (in.readInt() == 1);
    }

    public IncomingTextMessage(IncomingTextMessage base, String newBody) {
        this.message = newBody;
        this.sender = base.getSender();
        this.senderDeviceId = base.getSenderDeviceId();
        this.protocol = base.getProtocol();
        this.serviceCenterAddress = base.getServiceCenterAddress();
        this.replyPathPresent = base.isReplyPathPresent();
        this.pseudoSubject = base.getPseudoSubject();
        this.sentTimestampMillis = base.getSentTimestampMillis();
        this.groupId = base.getGroupId();
        this.push = base.isPush();
    }

    public IncomingTextMessage(List<IncomingTextMessage> fragments) {
        StringBuilder body = new StringBuilder();

        for (IncomingTextMessage message : fragments) {
            body.append(message.getMessageBody());
        }

        this.message = body.toString();
        this.sender = fragments.get(0).getSender();
        this.senderDeviceId = fragments.get(0).getSenderDeviceId();
        this.protocol = fragments.get(0).getProtocol();
        this.serviceCenterAddress = fragments.get(0).getServiceCenterAddress();
        this.replyPathPresent = fragments.get(0).isReplyPathPresent();
        this.pseudoSubject = fragments.get(0).getPseudoSubject();
        this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis();
        this.groupId = fragments.get(0).getGroupId();
        this.push = fragments.get(0).isPush();
    }

    protected IncomingTextMessage(String sender, String groupId) {
        this.message = "";
        this.sender = sender;
        this.senderDeviceId = RecipientDevice.DEFAULT_DEVICE_ID;
        this.protocol = 31338;
        this.serviceCenterAddress = "Outgoing";
        this.replyPathPresent = true;
        this.pseudoSubject = "";
        this.sentTimestampMillis = System.currentTimeMillis();
        this.groupId = groupId;
        this.push = true;
    }

    public long getSentTimestampMillis() {
        return sentTimestampMillis;
    }

    public String getPseudoSubject() {
        return pseudoSubject;
    }

    public String getMessageBody() {
        return message;
    }

    public IncomingTextMessage withMessageBody(String message) {
        return new IncomingTextMessage(this, message);
    }

    public String getSender() {
        return sender;
    }

    public int getSenderDeviceId() {
        return senderDeviceId;
    }

    public int getProtocol() {
        return protocol;
    }

    public String getServiceCenterAddress() {
        return serviceCenterAddress;
    }

    public boolean isReplyPathPresent() {
        return replyPathPresent;
    }

    public boolean isKeyExchange() {
        return false;
    }

    public boolean isSecureMessage() {
        return false;
    }

    public boolean isPreKeyBundle() {
        return false;
    }

    public boolean isEndSession() {
        return false;
    }

    public boolean isPush() {
        return push;
    }

    public String getGroupId() {
        return groupId;
    }

    public boolean isGroup() {
        return false;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeString(message);
        out.writeString(sender);
        out.writeInt(senderDeviceId);
        out.writeInt(protocol);
        out.writeString(serviceCenterAddress);
        out.writeInt(replyPathPresent ? 1 : 0);
        out.writeString(pseudoSubject);
        out.writeLong(sentTimestampMillis);
        out.writeString(groupId);
        out.writeInt(push ? 1 : 0);
    }
}
